﻿using DotNet.Utilities.WpfHelpers;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WPFPractice.Windows
{
    /// <summary>
    /// WPF按钮拖动和调整大小功能演示
    /// </summary>
    public partial class WinButtonMoveResize : Window
    {
        #region 成员

        private Control _control;
        private int _btnNum = 0;

        #endregion

        public WinButtonMoveResize()
        {
            InitializeComponent();

            this.DataContext = this;
            SetCommandMethod();
        }

        #region 命令

        public ICommand AddBtnCommand { get; set; }

        public ICommand DelBtnCommand { get; set; }

        #endregion

        /// <summary>
        /// 命令方法赋值（在构造方法中调用）
        /// </summary>
        private void SetCommandMethod()
        {
            AddBtnCommand ??= new RelayCommand(o => true, async o =>
            {
                AddBtnHandler();
            });

            DelBtnCommand ??= new RelayCommand(o => true, async o =>
            {
                DelBtnHandler();
            });
        }

        /// <summary>
        /// 设置控件在Canvas容器中的位置;
        /// </summary>
        private void SetControlLocation(Control control, Point point)
        {
            Canvas.SetLeft(control, point.X);
            Canvas.SetTop(control, point.Y);
        }

        /// <summary>
        /// 添加按钮
        /// </summary>
        private void AddBtnHandler()
        {
            string btnContent = GetBtnContent();

            Button btn = new Button
            {
                Name = "btn" + btnContent,
                Content = "btn" + btnContent,
                Width = 80,
                Height = 20,
            };

            _control = btn;
            AddContorlToCanvas(_control);
            SetControlLocation(_control, new Point(163, 55));
        }

        /// <summary>
        /// 添加控件到界面;
        /// </summary>
        /// <param name="control"></param>
        private void AddContorlToCanvas(Control control)
        {
            control.MouseDown += MyMouseDown;
            control.MouseLeave += MyMouseLeave;
            //_control.MouseMove += MyMouseMove;
            control.KeyDown += MyKeyDown;

            //解决鼠标左键无法触发 MouseDown 的问题;
            control.AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(MyMouseDown), true);
            control.AddHandler(Button.MouseMoveEvent, new MouseEventHandler(MyMouseMove), true);

            CanvasMain.Children.Add(control);

            if (control is Button)
            {
                //模板中设置按钮文字换行(模板资源在App.xaml中);
                control.SetResourceReference(ContentTemplateProperty, "DataTemplateButtonWrap");
                _btnNum++;
            }
        }

        /// <summary>
        /// 生成按钮内容
        /// </summary>
        /// <returns></returns>
        private string GetBtnContent()
        {
            return (_btnNum + 1).ToString().PadLeft(3, '0');
        }

        /// <summary>
        /// 删除按钮
        /// </summary>
        private void DelBtnHandler()
        {
            CanvasMain.Children.Remove(_control);
        }

        #region 实现窗体内的控件拖动

        const int Band = 5;
        const int BtnMinWidth = 10;
        const int BtnMinHeight = 10;
        private EnumMousePointPosition _enumMousePointPosition;
        private Point _point; //记录鼠标上次位置;

        #region 按钮拖动

        /// <summary>
        /// 鼠标按下
        /// </summary>
        private void MyMouseDown(object sender, MouseEventArgs e)
        {
            //选择当前的按钮
            Button button = (Button)sender;
            _control = button;
            //Point point = e.GetPosition(CanvasMain);

            //左键点击按钮后可按WSAD进行上下左右移动;
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                button.KeyDown += new KeyEventHandler(MyKeyDown);
            }

            double left = Canvas.GetLeft(_control);
            double top = Canvas.GetTop(_control);

            //右键点击按钮可向选定方向生成新按钮;
            if (e.RightButton == MouseButtonState.Pressed)
            {
                Button btn = new Button
                {
                    Name = "btn" + GetBtnContent(), 
                    Content = GetStrEndNumAddOne(button.Content.ToString())
                };

                CheckRepeat(btn.Content.ToString());

                btn.Width = _control.Width;
                btn.Height = _control.Height;

                if (rbUpper.IsChecked == true)//上
                {
                    int h = txtUpper.Text.Trim() == "" ? 0 : Convert.ToInt32(txtUpper.Text.Trim());
                    SetControlLocation(btn, new Point(left, top - _control.Height - h));
                }
                if (rbLower.IsChecked == true)//下
                {
                    int h = txtLower.Text.Trim() == "" ? 0 : Convert.ToInt32(txtLower.Text.Trim());
                    SetControlLocation(btn, new Point(left, top + _control.Height + h));
                }
                if (rbLeft.IsChecked == true)//左
                {
                    int w = txtLeft.Text.Trim() == "" ? 0 : Convert.ToInt32(txtLeft.Text.Trim());
                    SetControlLocation(btn, new Point(left - _control.Width - w, top));
                }
                if (rbRight.IsChecked == true)//右
                {
                    int w = txtRight.Text.Trim() == "" ? 0 : Convert.ToInt32(txtRight.Text.Trim());
                    SetControlLocation(btn, new Point(left + _control.Width + w, top));
                }

                _control = btn;
                AddContorlToCanvas(_control);
            }

            //中键点击按钮可进行信息编辑;
            //if (e.Button == MouseButtons.Middle)
            //{
            //    _control.ForeColor = Color.Red;
            //    string width = _control.Width.ToString();
            //    string height = _control.Height.ToString();
            //    string text = _control.Text;
            //    FrmMessage f = new FrmMessage(width, height, text);
            //    f.StartPosition = FormStartPosition.CenterScreen;
            //    f.ShowDialog();
            //    if (f.w != "")
            //    {
            //        _control.Width = Convert.ToInt32(f.w);
            //    }
            //    if (f.h != "")
            //    {
            //        _control.Height = Convert.ToInt32(f.h);
            //    }
            //    if (f.t != "")
            //    {
            //        _control.Text = f.t;
            //    }
            //    _control.ForeColor = Color.Black;
            //}
        }

        /// <summary>
        /// 检查重复内容按钮
        /// </summary>
        /// <param name="content"></param>
        private void CheckRepeat(string content)
        {
            foreach (Control c in CanvasMain.Children)
            {
                if (c is Button btn)
                {
                    if (content == btn.Content.ToString())
                    {
                        MessageBox.Show("出现重复按钮内容：" + content, "提示");
                        return;
                    }
                }
            }
        }

        /// <summary>
        /// 获取非纯数字字符串的数值加一结果;
        /// </summary>
        private string GetStrEndNumAddOne(string str)
        {
            int numberIndex = 0; //数字部分的起始位置;
            int charIndex = 0;
            foreach (char tempchar in str.ToCharArray())
            {
                charIndex++;
                if (!char.IsNumber(tempchar))
                {
                    numberIndex = charIndex;
                }
            }

            string prefix = str.Substring(0, numberIndex);
            string numberStrOrigin = str.Remove(0, numberIndex);
            string numberStrTemp = "";

            if (numberStrOrigin != "")
            {
                numberStrTemp = (Convert.ToInt32(numberStrOrigin) + 1).ToString();
            }

            string result = "";
            if (numberStrOrigin.Length <= numberStrTemp.Length)
            {
                result = prefix + numberStrTemp;
            }
            else
            {
                result = prefix + numberStrTemp.PadLeft(numberStrOrigin.Length, '0');
            }

            return result;
        }

        /// <summary>
        /// 鼠标离开
        /// </summary>
        private void MyMouseLeave(object sender, EventArgs e)
        {
            _enumMousePointPosition = EnumMousePointPosition.MouseSizeNone;
            _control.Cursor = Cursors.Arrow;
        }

        /// <summary>
        /// 鼠标移动
        /// </summary>
        private void MyMouseMove(object sender, MouseEventArgs e)
        {
            _control = (Control)sender;
            double left = Canvas.GetLeft(_control);
            double top = Canvas.GetTop(_control);
            Point point = e.GetPosition(CanvasMain);
            double height = _control.Height;
            double width = _control.Width;

            if (e.LeftButton == MouseButtonState.Pressed)
            {
                switch (_enumMousePointPosition)
                {
                    case EnumMousePointPosition.MouseDrag:

                        SetControlLocation(_control, new Point(left + point.X - _point.X, top + point.Y - _point.Y));

                        break;

                    case EnumMousePointPosition.MouseSizeBottom:

                        height += point.Y - _point.Y;

                        break;

                    case EnumMousePointPosition.MouseSizeBottomRight:

                        width += point.X - _point.X;
                        height += point.Y - _point.Y;

                        break;

                    case EnumMousePointPosition.MouseSizeRight:

                        width += point.X - _point.X;

                        break;

                    case EnumMousePointPosition.MouseSizeTop:

                        SetControlLocation(_control, new Point(left, top + point.Y - _point.Y));
                        height -= (point.Y - _point.Y);

                        break;

                    case EnumMousePointPosition.MouseSizeLeft:

                        SetControlLocation(_control, new Point(left + point.X - _point.X, top));
                        width -= (point.X - _point.X);

                        break;

                    case EnumMousePointPosition.MouseSizeBottomLeft:

                        SetControlLocation(_control, new Point(left + point.X - _point.X, top));
                        width -= (point.X - _point.X);
                        height += point.Y - _point.Y;

                        break;

                    case EnumMousePointPosition.MouseSizeTopRight:

                        SetControlLocation(_control, new Point(left, top + point.Y - _point.Y));
                        width += (point.X - _point.X);
                        height -= (point.Y - _point.Y);

                        break;

                    case EnumMousePointPosition.MouseSizeTopLeft:

                        SetControlLocation(_control, new Point(left + point.X - _point.X, top + point.Y - _point.Y));
                        width -= (point.X - _point.X);
                        height -= (point.Y - _point.Y);

                        break;

                    default:

                        break;
                }

                //记录光标拖动到的当前点
                _point.X = point.X;
                _point.Y = point.Y;

                if (width < BtnMinWidth) width = BtnMinWidth;
                if (height < BtnMinHeight) height = BtnMinHeight;
                _control.Width = width;
                _control.Height = height;
            }
            else
            {
                _enumMousePointPosition = GetMousePointPosition(_control, e); //'判断光标的位置状态

                switch (_enumMousePointPosition) //'改变光标
                {
                    case EnumMousePointPosition.MouseSizeNone:

                        _control.Cursor = Cursors.Arrow;       //'箭头

                        break;

                    case EnumMousePointPosition.MouseDrag:

                        _control.Cursor = Cursors.SizeAll;     //'四方向

                        break;

                    case EnumMousePointPosition.MouseSizeBottom:

                        _control.Cursor = Cursors.SizeNS;      //'南北

                        break;

                    case EnumMousePointPosition.MouseSizeTop:

                        _control.Cursor = Cursors.SizeNS;      //'南北

                        break;

                    case EnumMousePointPosition.MouseSizeLeft:

                        _control.Cursor = Cursors.SizeWE;      //'东西

                        break;

                    case EnumMousePointPosition.MouseSizeRight:

                        _control.Cursor = Cursors.SizeWE;      //'东西

                        break;

                    case EnumMousePointPosition.MouseSizeBottomLeft:

                        _control.Cursor = Cursors.SizeNESW;    //'东北到南西

                        break;

                    case EnumMousePointPosition.MouseSizeBottomRight:

                        _control.Cursor = Cursors.SizeNWSE;    //'东南到西北

                        break;

                    case EnumMousePointPosition.MouseSizeTopLeft:

                        _control.Cursor = Cursors.SizeNWSE;    //'东南到西北

                        break;

                    case EnumMousePointPosition.MouseSizeTopRight:

                        _control.Cursor = Cursors.SizeNESW;    //'东北到南西

                        break;

                    default:

                        break;
                }
            }
        }

        /// <summary>
        /// 按键WSAD(上下左右)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MyKeyDown(object sender, KeyEventArgs e)
        {
            double left = Canvas.GetLeft(_control);
            double top = Canvas.GetTop(_control);

            switch (e.Key)
            {
                case Key.W://上
                {
                    SetControlLocation(_control, new Point(left, top-1));
                    break;
                }
                case Key.S://下
                {
                    SetControlLocation(_control, new Point(left, top+1));
                    break;
                }
                case Key.A://左
                {
                    SetControlLocation(_control, new Point(left-1, top));
                    break;
                }
                case Key.D://右
                {
                    SetControlLocation(_control, new Point(left+1, top));
                    break;
                }
            }
        }

        #endregion 按钮拖动

        #region 鼠标位置

        /// <summary>
        /// 鼠标指针位置枚举;
        /// </summary>
        private enum EnumMousePointPosition
        {
            /// <summary>
            /// 无
            /// </summary>
            MouseSizeNone = 0,

            /// <summary>
            /// 拉伸右边框
            /// </summary>
            MouseSizeRight = 1,

            /// <summary>
            /// 拉伸左边框
            /// </summary>
            MouseSizeLeft = 2,

            /// <summary>
            /// 拉伸下边框
            /// </summary>
            MouseSizeBottom = 3,

            /// <summary>
            /// 拉伸上边框
            /// </summary>
            MouseSizeTop = 4,

            /// <summary>
            /// 拉伸左上角
            /// </summary>
            MouseSizeTopLeft = 5,

            /// <summary>
            /// 拉伸右上角
            /// </summary>
            MouseSizeTopRight = 6,

            /// <summary>
            /// 拉伸左下角
            /// </summary>
            MouseSizeBottomLeft = 7,

            /// <summary>
            /// 拉伸右下角
            /// </summary>
            MouseSizeBottomRight = 8,       

            /// <summary>
            /// 鼠标拖动
            /// </summary>
            MouseDrag = 9
        }

        /// <summary>
        /// 获取鼠标指针位置;
        /// </summary>
        /// <param name="control"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private EnumMousePointPosition GetMousePointPosition(Control control, MouseEventArgs e)
        {
            Size size = control.RenderSize;
            Point point = e.GetPosition(control);

            Point pointCanvas = e.GetPosition(CanvasMain);
            _point.X = pointCanvas.X;
            _point.Y = pointCanvas.Y;

            if ((point.X >= -1 * Band) | (point.X <= size.Width) | (point.Y >= -1 * Band) | (point.Y <= size.Height))
            {
                if (point.X < Band)
                {
                    if (point.Y < Band)
                    {
                        return EnumMousePointPosition.MouseSizeTopLeft;
                    }
                    else
                    {
                        if (point.Y > -1 * Band + size.Height)
                        {
                            return EnumMousePointPosition.MouseSizeBottomLeft;
                        }
                        else
                        {
                            return EnumMousePointPosition.MouseSizeLeft;
                        }
                    }
                }
                else
                {
                    if (point.X > -1 * Band + size.Width)
                    {
                        if (point.Y < Band)
                        {
                            return EnumMousePointPosition.MouseSizeTopRight;
                        }
                        else
                        {
                            if (point.Y > -1 * Band + size.Height)
                            {
                                return EnumMousePointPosition.MouseSizeBottomRight;
                            }
                            else
                            {
                                return EnumMousePointPosition.MouseSizeRight;
                            }
                        }
                    }
                    else
                    {
                        if (point.Y < Band)
                        {
                            return EnumMousePointPosition.MouseSizeTop;
                        }
                        else
                        {
                            if (point.Y > -1 * Band + size.Height)
                            {
                                return EnumMousePointPosition.MouseSizeBottom;
                            }
                            else
                            {
                                return EnumMousePointPosition.MouseDrag;
                            }
                        }
                    }
                }
            }
            else
            {
                return EnumMousePointPosition.MouseSizeNone;
            }
        }

        #endregion 鼠标位置

        #endregion 实现窗体内的控件拖动
    }
}
